package com.example.sdk.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import java.io.*;
import java.security.*;
import java.util.Base64;

public class RSAUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class);
    /** 算法名称 */
    private static final String ALGORITHM =  "RSA";

    public static String ENCODE = "UTF-8";

    /** 默认密钥大小 */
    private static final int KEY_SIZE = 1024;
    /** 用来指定保存密钥对的文件名和存储的名称 */
    private static final String PUBLIC_KEY_NAME = "publicKey";
    private static final String PRIVATE_KEY_NAME = "privateKey";
    private static final String PUBLIC_FILENAME = "publicKey.properties";
    private static final String PRIVATE_FILENAME = "privateKey.properties";

    public static final String PRIVATE_KEY_FILE = "d:/pri.pem";
    //公钥文件路径
    public static final String PUBLIC_KEY_FILE = "d:/pub.pem";

    public static int KEYSIZE = 512;

    /** 密钥对生成器 */
    private static KeyPairGenerator keyPairGenerator = null;

    private static KeyFactory keyFactory = null;
    /** 缓存的密钥对 */
    private static KeyPair keyPair = null;

    private static PublicKey publicKey = null;

    private static PrivateKey privateKey = null;

    /** Base64 编码/解码器 JDK1.8 */
    private static Base64.Decoder decoder = Base64.getDecoder();
    private static Base64.Encoder encoder = Base64.getEncoder();
    /** 初始化密钥工厂 */
    static{
//        try {
//            keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
//            keyFactory = KeyFactory.getInstance(ALGORITHM);
//        } catch (NoSuchAlgorithmException e) {
//            LOGGER.error(e.getMessage(),e);
//        }



    }

    public static void init() throws Exception {
        ObjectInputStream inputStreamPub = null;
        ObjectInputStream inputStreamPri = null;
        try {
            inputStreamPub = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
            inputStreamPri = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));

            try {
                publicKey = (PublicKey) inputStreamPub.readObject();
                privateKey = (PrivateKey) inputStreamPri.readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /** 私有构造器 */
    private RSAUtils(){}



    private static void generateKeyPair2() throws Exception {
        /** RSA算法要求有一个可信任的随机数源 */
        SecureRandom sr = new SecureRandom();
        /** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
        kpg.initialize(KEYSIZE, sr);
        /** 生成密匙对 */
        KeyPair kp = kpg.generateKeyPair();
        /** 得到公钥 */
        Key publicKey = kp.getPublic();
        /** 得到私钥 */
        Key privateKey = kp.getPrivate();
        /** 用对象流将生成的密钥写入文件 */
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
        oos1.writeObject(publicKey);
        oos2.writeObject(privateKey);
        /** 清空缓存，关闭文件输出流 */
        oos1.close();
        oos2.close();
    }

    public static String encrypt(String source) throws Exception {
        // generateKeyPair();
        /** 将文件中的公钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /** 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        String result = new String(encoder.encode(b1), ENCODE);
        return result;
    }

    /**
     * 解密算法 cryptograph:密文
     */
    public static String decrypt(String cryptograph) throws Exception {
        /** 将文件中的私钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();

        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] b1 = decoder.decode(cryptograph.getBytes(ENCODE));
        /** 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    public static void main(String[] args) throws Exception {
//        generateKeyPair2(); //生成密匙对
//        System.out.println(encrypt("11111111111111111111111111111111"));
//        String encodeString = "AZWs/5yYl+fY8WvmtrsN4OzE8Ax9IduBvjL1NPQXrcuU5LyBvA2pdPyncdmiGZsSz5sj7L8bw2+fG+KVJIRaug==";
//        System.out.println(decrypt(encodeString));

        String aes = decrypt("KazDxfUpm5TEIj/lcSztklo6wbSKokq+Zncj9Rj2GxMXoqeAPyJ1rwsAAo2Ux00Ll/Ts5hM+/Lvj7dyBfYJryg==");
        System.out.println("aesKey is " + aes);
        //16进制密文转换为2进制再解密
        String result = "162EA268367FD86C1CC69E97CE9B1A1BFCD5A0741CDFC5EF948E933FECECA1B6415F01143B2F285A854F3C105C7D470D0DA0F923F0377F648BD1660A974EFBBEBE504CC80F79ACD0C6DD1FFE3A501EF4B309F0353231EB38A1F89834325F27FEC3C88BB74377281D773B2B63DED07AA42578CB70623258AB4DDBFB394EE24D9AA78706E433E196FDE47AA7BEEC6891A2FAFE72C1E56CAEEACC6F0A605BD032B4761D4701061BDAA13A850F0A3EE5B4D6";
        //如果的到的是16进制密文，别忘了先转为2进制再解密
        byte[] twoStrResult = AESUtils.parseHexStr2Byte(result);
        System.out.println(new String(AESUtils.decrypt(twoStrResult, aes)));
    }
}
